package com.ctshk.rpc.bus.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.constant.RedisConstants;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.IsDeletedCode;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.enums.bus.BusLineStatusCode;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.req.MainData;
import com.ctshk.common.req.MainTreeData;
import com.ctshk.common.utils.Assist;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.HktBusUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.bus.dto.BusLineDTO;
import com.ctshk.rpc.bus.dto.BusLineListDTO;
import com.ctshk.rpc.bus.dto.Constants;
import com.ctshk.rpc.bus.dto.es.BusLineCacheDTO;
import com.ctshk.rpc.bus.entity.BusLine;
import com.ctshk.rpc.bus.entity.BusLineSeat;
import com.ctshk.rpc.bus.entity.BusLineStops;
import com.ctshk.rpc.bus.entity.BusStops;
import com.ctshk.rpc.bus.mapper.BusLineMapper;
import com.ctshk.rpc.bus.mapper.BusLineSeatMapper;
import com.ctshk.rpc.bus.mapper.BusLineStopsMapper;
import com.ctshk.rpc.bus.mapper.BusStopsMapper;
import com.ctshk.rpc.bus.req.BusArriveCityListByLineQueryReq;
import com.ctshk.rpc.bus.req.BusDepartureCityListByLineQueryReq;
import com.ctshk.rpc.bus.req.BusLinePageReq;
import com.ctshk.rpc.bus.req.BusLineQueryReq;
import com.ctshk.rpc.bus.req.BusLineReq;
import com.ctshk.rpc.bus.req.BusStopsListByLineQueryReq;
import com.ctshk.rpc.bus.service.IBusLineService;
import com.google.common.collect.Maps;

/**
 * <p>
 * 巴士线路管理 服务实现类
 * </p>
 *
 * @author 彭柳霖
 * @since 2021-02-08
 */
@DubboService
public class BusLineServiceImpl extends ServiceImpl<BusLineMapper, BusLine> implements IBusLineService {

    @Autowired
    private BusLineMapper busLineMapper;

    @Autowired
    private BusLineSeatMapper busLineSeatMapper;

    @Autowired
    private BusStopsMapper busStopsMapper;

    @Autowired
    private BusLineStopsMapper busLineStopsMapper;

    @Autowired
    RedisTemplate<String,String> redisTemplate;

    @Override
    public List<BusLineDTO> queryBusLine(BusLineQueryReq busLineQueryReq) {
        List<BusLine> busLineList = busLineMapper.queryList(busLineQueryReq);
        List<BusLineDTO> busLineDTOList = EntityUtil.copyList(busLineList, BusLineDTO.class);

        Assist.forEach(busLineDTOList, dto -> {
            //座位号
        	List<String> seatNumberList = busLineSeatMapper.querySeatNumberListByLine(dto.getId());
            dto.setSeatNumberList(seatNumberList);

            //始发站
            if (dto.getDepartureStationId() != null) {
                dto.getStationList().add(new MainData(dto.getDepartureStationId(), dto.getDepartureStationName()));
            }

            //经停站
            List<MainData> itemStopsList = busLineStopsMapper.queryDictListByLine(dto.getId());
            Assist.add(dto.getStationList(), itemStopsList);

            //终点站
            if (dto.getTerminusId() != null) {
                dto.getStationList().add(new MainData(dto.getTerminusId(), dto.getTerminusName()));
            }
        });
        return busLineDTOList;
    }

    /**
     * 根据线路id查询巴士路线
     *
     * @param lineId
     * @return
     */
    @Override
    public BusLineDTO queryByLineId(Long lineId) {
        BusLine busLine = busLineMapper.selectById(lineId);
        BusLineDTO busLineDTO = EntityUtil.copy(busLine, BusLineDTO.class);
        return busLineDTO;
    }

    /**
     * 中港通巴士路线信息导入
     */
    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public Result importHktBusLine(TokenUser user) {
        Map<String, Object> result = Maps.newHashMap();
        try {
            result = HktBusUtil.getRoutes();
        } catch (Exception e) {
            throw new BusinessException(SystemError.SYS_415);
        }
        Map routes = (Map) result.get("routes");
        if (Objects.isNull(routes)) {
            return Result.failed(SystemError.SYS_411);
        }
        List<Map> route = (List<Map>) routes.get("route");
        if (CollectionUtils.isEmpty(route)) {
            return Result.failed(SystemError.SYS_411);
        }
        route.stream().forEach(map -> {

            //先删后增
            busLineMapper.deleteById(Long.valueOf((String) map.get("routeId")));

            BusLine busLine = new BusLine();
            busLine.setId(Long.valueOf((String) map.get("routeId")));
            busLine.setBusCompaniesId(Long.valueOf("8888"));
            busLine.setBusCompaniesName("中港通巴士");
            busLine.setLineName((String) map.get("routeName"));
            busLine.setDepartureCityId(Long.valueOf((String) map.get("fromCityId")));
            busLine.setDepartureCityName((String) map.get("fromCityName"));
            busLine.setArriveCityId(Long.valueOf((String) map.get("toCityId")));
            busLine.setArriveCityName((String) map.get("toCityCName"));
            busLine.setStatus(Constants.VALID);
            busLine.setGmtCreate(LocalDateTime.now());
            busLine.setCreateId(user.getId());
            busLine.setIsDeleted(IsDeletedCode.YES.getCode());
            busLineMapper.insert(busLine);
        });

        return Result.success();
    }


    /**
     * 分页查询巴士线路列表
     *
     * @param req
     * @return
     */

    @Override
    public PageResponse<BusLineListDTO> queyList(BusLinePageReq req) {

        IPage<BusLineListDTO> agentPage = new Page<>(req.getPageNo(), req.getPageSize());
        agentPage = busLineMapper.queryList(req, agentPage);
        PageResponse<BusLineListDTO> result = new PageResponse<>(agentPage.getRecords(), agentPage.getCurrent() == 1,
                agentPage.getTotal() <= (agentPage.getCurrent() * agentPage.getSize()),
                agentPage.getTotal(), agentPage.getCurrent(), agentPage.getSize());
        return result;
    }

    /**
     * 新增线路信息
     *
     * @param busLineReq
     * @param user
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Result saveBusLine(BusLineReq busLineReq, TokenUser user) {
        if (user == null) {
            return Result.failed(SystemError.USER_1000);
        }
        if (busLineReq == null) {
            return Result.failed(SystemError.BUS_PRODUCT_9003);
        }

        //保存巴士线路表
        BusLine busLine = EntityUtil.copy(busLineReq, BusLine.class);
        Long busLineId = SnowflakeIdWorker.nextId();
        busLine.setId(busLineId);
        busLine.setCreateId(user.getId());
        busLine.setGmtCreate(LocalDateTime.now());
        busLine.setStatus(Constants.VALID);
        busLine.setIsDeleted(Constants.NOT_DELETE);
        busLineMapper.insert(busLine);

        //保存线路座位信息
        String seatNumbers = Assist.defaultString(busLineReq.getSeatNumbers());
        seatNumbers = seatNumbers.replace("，", ",");
        List<String> seatNumbersList = Arrays.asList(seatNumbers.split(","));
        for (String seatNumber : seatNumbersList) {
            BusLineSeat busLineSeat = new BusLineSeat();
            busLineSeat.setId(SnowflakeIdWorker.nextId());
            busLineSeat.setLineId(busLineId);
            busLineSeat.setSeatNumber(seatNumber);
            busLineSeatMapper.insert(busLineSeat);
        }

        //保存巴士线路站点关联表 
        if (Assist.isNotEmpty(busLineReq.getSiteNames())) {
            List<Long> siteIdList = Assist.forEachToList(busLineReq.getSiteNames(), MainTreeData::getId);
            List<BusStops> busStopsList = busStopsMapper.selectList(new QueryWrapper<BusStops>().lambda().in(BusStops::getId, siteIdList));

            for (BusStops busStops : busStopsList) {
                BusLineStops busLineStops = new BusLineStops();
                busLineStops.setId(SnowflakeIdWorker.nextId());
                busLineStops.setLineId(busLineId);
                busLineStops.setStopsId(busStops.getId());
                busLineStopsMapper.insert(busLineStops);
            }
        }

        return Result.success();
    }


    /**
     * 修改线路信息
     *
     * @param busLineReq
     * @param user
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Result updateBusLine(BusLineReq busLineReq, TokenUser user) {

        if (user == null) {
            return Result.failed(SystemError.USER_1000);
        }
        if (busLineReq == null) {
            return Result.failed(SystemError.BUS_PRODUCT_9003);
        }


        //更新巴士路线表
        BusLine busLine = busLineMapper.selectById(busLineReq.getId());
        if (Objects.isNull(busLine)) {
            return Result.failed(SystemError.BUS_PRODUCT_9008);
        }

        busLine = EntityUtil.copy(busLineReq, BusLine.class);
        busLine.setModifiedId(user.getId());
        busLine.setGmtModified(LocalDateTime.now());
        busLineMapper.updateById(busLine);

        //更新线路座位信息(先删后插入)
        busLineSeatMapper.delete(new QueryWrapper<BusLineSeat>().lambda().eq(BusLineSeat::getLineId, busLine.getId()));
        String seatNumbers = busLineReq.getSeatNumbers();
        List<String> seatNumbersList = Arrays.asList(seatNumbers.split(","));

        for (String seatNumber : seatNumbersList) {
            BusLineSeat busLineSeat = new BusLineSeat();
            busLineSeat.setId(SnowflakeIdWorker.nextId());
            busLineSeat.setLineId(busLine.getId());
            busLineSeat.setSeatNumber(seatNumber);
            busLineSeatMapper.insert(busLineSeat);
        }

        //更新巴士线路站点关连表((先删后插入))
        busLineStopsMapper.delete(new QueryWrapper<BusLineStops>().lambda().eq(BusLineStops::getLineId, busLine.getId()));


        //保存巴士线路站点关联表
        if (Assist.isNotEmpty(busLineReq.getSiteNames())) {
            List<Long> siteIdList = Assist.forEachToList(busLineReq.getSiteNames(), MainTreeData::getId);
            List<BusStops> busStopsList = busStopsMapper.selectList(new QueryWrapper<BusStops>().lambda().in(BusStops::getId, siteIdList));

            for (BusStops busStops : busStopsList) {
                BusLineStops busLineStops = new BusLineStops();
                busLineStops.setId(SnowflakeIdWorker.nextId());
                busLineStops.setLineId(busLine.getId());
                busLineStops.setStopsId(busStops.getId());
                busLineStopsMapper.insert(busLineStops);
            }

        }
        return Result.success();
    }

    /**
     * 查询巴士线路详情信息
     *
     * @param id
     * @return
     */
    @Override
    public BusLineDTO queryDetail(Long id) {
        BusLine busline = busLineMapper.selectById(id);
        BusLineDTO busLineDTO = EntityUtil.copy(busline, BusLineDTO.class);

        //查询座位表信息
        List<BusLineSeat> busLineSeatList = busLineSeatMapper.selectList(new QueryWrapper<BusLineSeat>().lambda().eq(BusLineSeat::getLineId, busline.getId()));
        String seatNumbers = busLineSeatList.stream().map(n -> n.getSeatNumber()).collect(Collectors.joining(","));
        busLineDTO.setSeatNumbers(seatNumbers);
        busLineDTO.setSeatNumberList(Assist.forEachToList(busLineSeatList, BusLineSeat::getSeatNumber));

        if (Assist.isNotEmpty(busLineSeatList)) {
            //查询巴士线路站点关联表
            List<BusLineStops> busLineStopsList = busLineStopsMapper.selectList(new QueryWrapper<BusLineStops>().lambda().eq(BusLineStops::getLineId, busline.getId()));
            List<Long> stopIdList = busLineStopsList.stream().map(BusLineStops::getStopsId).collect(Collectors.toList());

            //查询巴士站点表
            if (Assist.isNotEmpty(busLineStopsList)) {
                List<BusStops> busStopsList = busStopsMapper.selectList(new QueryWrapper<BusStops>().lambda().in(BusStops::getId, stopIdList));
                if (Assist.isNotEmpty(busStopsList)) {
                	String siteNames = busStopsList.stream().map(n -> n.getSiteName()).collect(Collectors.joining(","));
                	String siteIds = busStopsList.stream().map(n -> n.getId().toString()).collect(Collectors.joining(","));
                	
                	String[] siteNameArray = siteNames.split(",");
                	String[] siteIdArray = siteIds.split(",");
                	MainData[] siteInfoArray = new MainData[siteNameArray.length];
                	for (int i = 0; i < siteNameArray.length; i++) {
                		MainData mainData = new MainData();
                		mainData.setValue(Long.valueOf(siteIdArray[i]));
                		mainData.setLabel(siteNameArray[i]);
                		siteInfoArray[i] = mainData;
                	}
                	busLineDTO.setSiteNames(siteInfoArray);
                }
            }
        }
        return busLineDTO;
    }


    /**
     * 巴士线路有效无效设置
     *
     * @param id
     */
    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public Result isValid(long id, TokenUser user) {
        if (user == null) {
            return Result.failed(SystemError.USER_1000);
        }
        BusLine busLine = busLineMapper.selectById(id);
        if (Objects.isNull(busLine)) {
            return Result.failed(SystemError.BUS_PRODUCT_9008);
        }
        if (Constants.VALID.equals(busLine.getStatus())) {
            busLine.setStatus(Constants.INVALID); //设置为无效
        } else {
            busLine.setStatus(Constants.VALID); //设置为有效
        }
        busLine.setModifiedId(user.getId());
        busLine.setGmtModified(LocalDateTime.now());
        busLineMapper.updateById(busLine);

        return Result.success();
    }

    /**
     * 查询巴士线路的出发城市列表
     */
    @Override
    public Result<List<MainData>> queryDepartureCityListByLine(BusDepartureCityListByLineQueryReq req) {
        List<MainData> list = getBaseMapper().queryDepartureCityListByLine(req);
        return new Result<>(list);
    }

    /**
     * 查询巴士线路的到达城市列表
     */
    @Override
    public Result<List<MainData>> queryArriveCityListByLine(BusArriveCityListByLineQueryReq req) {
        List<MainData> list = getBaseMapper().queryArriveCityListByLine(req);
        return new Result<>(list);
    }

    /**
     * 查询巴士线路的站点列表
     */
    @Override
    public Result<List<MainData>> queryStopsListByLine(BusStopsListByLineQueryReq req) {
    	List<MainData> list = new ArrayList<>();
    	Assist.add(list, getBaseMapper().queryDepartureStopsListByLine(req));
    	Assist.add(list, getBaseMapper().queryStopsListByLine(req));
    	Assist.add(list, getBaseMapper().queryTerminusStopsListByLine(req));
        return new Result<>(list);
    }

    /**
     * 查询所有有效的巴士路线列表
     * @return
     */
    @Override
    public List<BusLineCacheDTO> findBusLineList(List<Long> ids,LocalDateTime now) {
        LambdaQueryWrapper<BusLine> wrapper = Wrappers.<BusLine>lambdaQuery().eq(BusLine::getIsDeleted, IsDeletedCode.NO.getCode());
        wrapper.eq(BusLine::getStatus, BusLineStatusCode.VALID.getCode());
        if(now != null){
            LocalDateTime updateTime = JSON.parseObject(redisTemplate.opsForValue().get(RedisConstants.BUS_UPDATE_TIME), LocalDateTime.class);
            wrapper.ge(now.isAfter(updateTime),BusLine::getGmtModified,now);
        }
        wrapper.in(ids!=null && ids.size()> 0, BusLine::getId,ids);
        List<BusLine> busLines = busLineMapper.selectList(wrapper);
        return EntityUtil.copyList(busLines,BusLineCacheDTO.class);
    }


}
